package com.pb.infra.oth.util;

import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.util.IoUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.AbstractHttpEntity;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;

@Slf4j
@Component
public class CDRCBFileEncryptionRest {

    @Value("${file.dlp.ip}")
    private String ip;

    @Value("${file.dlp.port}")
    private String port;

    @Value("${file.path}")
    private String path;


    @Value("${file.dlp.isStart}")
    private Boolean isStart;


    /**
     * 文件加密(EasyExcel)
     *
     * @param excelWriter
     * @return response
     */
    public void fileEncryption(ExcelWriter excelWriter, HttpServletResponse response, String fileName) throws IOException {
        OutputStream os = response.getOutputStream();
        excelWriter.finish();
        InputStream in = new FileInputStream(fileName);
        byte[] bs = new byte[1024];
        int len = 0;
        while ((len = in.read(bs)) > -1) {
            response.getOutputStream().write(bs, 0, len);
        }
        in.close();
        os.flush();
        os.close();
        Files.deleteIfExists(
                Paths.get(fileName));

    }

    /**
     * 文件加密(POI)
     *
     * @param response
     * @param workbook
     */
    public void fileEncryption(Workbook workbook, HttpServletResponse response) throws IOException {

        OutputStream os = response.getOutputStream();

        String uri = "http://" + ip + ":" + port + "/sec-server/s/rs/uni/restfile/fileEncryption";//加密
        if (isStart) {
            String fileName = path + "/" + IdUtil.randomUUID() + ".xlsx";
            //生成临时文件
            ExportExcelUtil.workbookConvertorStream(workbook, fileName, path);

            try {
                CloseableHttpClient httpclient = HttpClients.createDefault();
                HttpPost post = new HttpPost(uri);
                File file = new File(fileName);
                post.addHeader("token", "EsafeNet."); //固定token
                post.addHeader("data~fileOffset", "0");
                post.addHeader("data~counSize", file.length() + "");
                InputStream in = new FileInputStream(fileName);
                AbstractHttpEntity entity = new InputStreamEntity(in);
                post.setEntity(entity);
                CloseableHttpResponse httpResponse = httpclient.execute(post);
                String result = httpResponse.getFirstHeader("data~returnFlag").getValue();
                if ("0".equals(result)) {//0 表示成功

                    InputStream ins = httpResponse.getEntity().getContent();
                    byte[] bs = new byte[1024];
                    int len = 0;
                    while ((len = ins.read(bs)) > -1) {
                        response.getOutputStream().write(bs, 0, len);
                    }

                }
                os.flush();
                os.close();
                in.close();

            } catch (Exception e) {
                e.printStackTrace();
            }
            Files.deleteIfExists(
                    Paths.get(fileName));
        } else {
            //普通导出
            workbook.write(os);
            os.flush();
            os.close();
        }
    }


    /**
     * 解密
     *
     * @throws FileNotFoundException
     */
    public InputStream fileDecryption(InputStream inputStream) throws FileNotFoundException {

        //生成文件
        String fileName = path + "/" + IdUtil.randomUUID() + ".xlsx";
        if (isStart) {
            CloseableHttpClient httpclient = HttpClients.createDefault();
            String uri = "http://" + ip + ":" + port + "/sec-server/s/rs/uni/restfile/fileDecryption";//解密
            HttpPost post = new HttpPost(uri);

            try {
                //生成临时加密文件
                FileOutputStream fileOutputStream = new FileOutputStream(fileName);
                fileOutputStream.write(IoUtils.toByteArray(inputStream));
                fileOutputStream.flush();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            File filesPath = new File(path);
            if (!filesPath.exists()) {
                filesPath.mkdirs();
            }
            File file = new File(fileName);
            post.addHeader("token", "EsafeNet."); //固定token
            post.addHeader("data~fileOffset", "0");
            post.addHeader("data~counSize", file.length() + "");
            try {
                InputStream fileInputStream = new FileInputStream(file);
                AbstractHttpEntity entity = new InputStreamEntity(fileInputStream);
                post.setEntity(entity);
                CloseableHttpResponse response = httpclient.execute(post);
                String result = response.getFirstHeader("data~returnFlag").getValue();
                if ("0".equals(result)) {
                    //0 表示成功
                    fileInputStream.close();
                    Files.deleteIfExists(
                            Paths.get(fileName));
                    return response.getEntity().getContent();
                } else if ("2".equals(result)) {
                    //2 明文无需解密
                    fileInputStream.close();
                    Files.deleteIfExists(
                            Paths.get(fileName));
                    return response.getEntity().getContent();
                } else {
                    log.debug("文件加密异常状态码(DLP加解密中间件系统开发测试接口文档):{}", result);
                    return null;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            return inputStream;
        }

        return null;
    }

    /**
     * 解密
     *
     * @param inputStream 文件流
     * @param file        文件
     * @return
     */
    public InputStream fileDecryption(InputStream inputStream, File file) {
        InputStream in = null;

        String uri = "http://" + ip + ":" + port + "/sec-server/s/rs/uni/restfile/fileDecryption";//加密
        if (isStart) {
            try {
                byte[] bytesByFile = FileBytetransfer.getBytesByFile(inputStream);
                if (checkFileIsEncryption(ip, port, bytesByFile, file).equals("1")) {
                    HttpResponse res = HttpRequest.post(uri)
                            .header("token", "EsafeNet.")
                            .header("data~fileOffset", "0")
                            .header("data~counSize", file.length() + "")
                            .body(bytesByFile)
                            .timeout(20000)//超时，毫秒
                            .execute();
                    String result = res.header("data~returnFlag");
                    if ("0".equals(result)) {//0 表示成功
                        in = res.bodyStream();
                    }
                    return in;
                } else {
                    return new FileInputStream(file);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            return inputStream;
        }
        return null;
    }


    /**
     * 判断文件是否是密文的接口
     *
     * @param ip          ip
     * @param port        端口号
     * @param file        文件
     * @param bytesByFile byte
     * @return 0：明文, 1：密文
     */
    public static String checkFileIsEncryption(String ip, String port, byte[] bytesByFile, File file) {
        String uri = "http://" + ip + ":" + port + "/sec-server/s/rs/uni/restfile/checkFileIsEncryption";
        HttpResponse res = HttpRequest.post(uri)
                .header("token", "EsafeNet.")
                .header("data~fileOffset", "0")
                .header("data~counSize", file.length() + "")
                .body(bytesByFile)
                .timeout(20000)//超时，毫秒
                .execute();

        String result = res.header("data~returnFlag");
//                0：明文
//                1：密文

        return result;

    }


    /**
     * 文件加密
     *
     * @param file
     * @return
     */
    public void fileEncryptionStream(File file, InputStream is) {
        OutputStream out = null;
        InputStream ins = null;
        String uri = "http://" + ip + ":" + port + "/sec-server/s/rs/uni/restfile/fileEncryption";//加密
        try {
            if (isStart) {
                byte[] bytes = FileBytetransfer.getBytesByFile(is);
                HttpResponse res = HttpRequest.post(uri)
                        .header("token", "EsafeNet.")
                        .header("data~fileOffset", "0")
                        .header("data~counSize", bytes.length + "")
                        .body(bytes)
                        .timeout(20000)//超时，毫秒
                        .execute();

                String result = res.header("data~returnFlag");
                if ("0".equals(result)) {//0 表示成功
                    ins = res.bodyStream();
                    byte[] bts = new byte[1024];
                    int len = 0;
                    out = new FileOutputStream(file);
                    while ((len = ins.read(bts)) > -1) {
                        out.write(bts, 0, len);
                    }
                    out.flush();
                }
            } else {
                out = new FileOutputStream(file);
                byte[] bts = new byte[1024];
                int len = 0;
                while ((len = is.read(bts)) > -1) {
                    out.write(bts, 0, len);
                }
                out.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != out) {
                    out.close();
                }
                if (null != ins) {
                    ins.close();
                }
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public static void main(String[] args) {

        CloseableHttpClient httpclient = HttpClients.createDefault();
        // String uri = "http://30.3.254.199:8080/sec-server/s/rs/uni/restfile/fileEncryption";//加密
        String uri = "http://30.3.254.199:8080/sec-server/s/rs/uni/restfile/fileDecryption";//解密
        HttpPost post = new HttpPost(uri);
        File file = new File("D:\\other\\upfile\\报表口径管理信息.xlsx");
        post.addHeader("token", "EsafeNet."); //固定token
        post.addHeader("data~fileOffset", "0");
        post.addHeader("data~counSize", file.length() + "");
        try {
            InputStream in = new FileInputStream(file);
            AbstractHttpEntity entity = new InputStreamEntity(in);
            post.setEntity(entity);
            CloseableHttpResponse response = httpclient.execute(post);
            String result = response.getFirstHeader("data~returnFlag").getValue();
            if ("0".equals(result)) {//0 表示成功
                OutputStream out = new FileOutputStream(new File("D:\\other\\upfile\\报表口径管理信息.xlsx"));
                InputStream ins = response.getEntity().getContent();
                byte[] bs = new byte[1024];
                int len = 0;
                while ((len = ins.read(bs)) > -1) {
                    out.write(bs, 0, len);
                }
                out.flush();
                out.close();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}


